import { Ref, ref } from 'vue';
import { IRecursiveTreeNode, NodeDropType } from '../recursive-tree-util';

export function getFormNode(
  itemEl: HTMLElement,
): IRecursiveTreeNode | undefined {
  const draggableItemEl = itemEl.closest('.vuedraggable') || itemEl;
  const draggableContext = (draggableItemEl as IData).__draggable_context;

  if (draggableContext && draggableContext.element) {
    const draggedNode = draggableContext.element as IRecursiveTreeNode;
    return draggedNode;
  }
}

export function useRecursiveNodeContent(
  props: {
    node: IRecursiveTreeNode;
    activeItem?: IRecursiveTreeNode;
    allowDrop?: (
      _draggingNode: IRecursiveTreeNode,
      _dropNode: IRecursiveTreeNode,
      _type: 'inner' | 'prev' | 'next',
    ) => boolean;
    allowDrag?: (draggingNode: IRecursiveTreeNode) => boolean;
  },
  onDrop: (
    _draggingNode: IRecursiveTreeNode,
    _dropNode: IRecursiveTreeNode,
    _dropType: NodeDropType,
  ) => void,
): {
  groupOptions: IData;
  draggableOptions: IData;
  isOverContainer: Ref<boolean>;
  isCenter: Ref<boolean>;
  itemGroupOptions: IData;
  draggableItemOptions: IData;
  isOverItemKey: Ref<string | number>;
  handleDragoverItem: (evt: MouseEvent, _nodeKey: string | number) => void;
  handleAdd: (evt: IData) => void;
  handleItemAdd: (evt: IData, _node: IRecursiveTreeNode) => void;
} {
  const isOverContainer = ref(false);
  const isCenter = ref(false);

  const isOverItemKey = ref<string | number>('');
  // 拖拽分组参数
  const groupOptions = {
    name: 'recursive-node',
    pull: true,
    put: true,
  };

  // 拖拽参数
  let dragEnterTarget: HTMLElement | null = null;
  let leaveCheckTimer: number | null = null;
  const draggableOptions = {
    tag: 'div',
    itemKey: 'id',
    animation: 200,
    onEnd: (): void => {
      isOverContainer.value = false;
    },
    onDragenter: (): void => {
      isOverContainer.value = true;
    },
    onDragover: (evt: MouseEvent): void => {
      evt.preventDefault(); // 必须加
      dragEnterTarget = evt.currentTarget as HTMLElement;
      if (leaveCheckTimer) {
        clearTimeout(leaveCheckTimer);
        leaveCheckTimer = null;
      }
    },
    onDragleave: (evt: MouseEvent): void => {
      leaveCheckTimer = window.setTimeout(() => {
        if (
          !dragEnterTarget?.contains(
            document.elementFromPoint(evt.clientX, evt.clientY) as Node,
          )
        ) {
          dragEnterTarget = null;
          isOverContainer.value = false;
          isOverItemKey.value = '';
        }
      }, 50); // 延迟一点判断
    },
  };

  // 拖拽分组参数
  let dragEnterTargetItem: HTMLElement | null = null;
  let leaveCheckTimerItem: number | null = null;
  const itemGroupOptions = {
    name: 'recursive-node',
    pull: true,
    put: true,
  };

  const handleDragoverItem = (evt: MouseEvent, _key: string | number): void => {
    evt.preventDefault(); // 必须加
    dragEnterTargetItem = evt.currentTarget as HTMLElement;
    if (leaveCheckTimerItem) {
      clearTimeout(leaveCheckTimerItem);
      leaveCheckTimerItem = null;
    }
    isOverItemKey.value = _key;
  };

  // 拖拽参数
  const draggableItemOptions = {
    tag: 'div',
    itemKey: 'id',
    animation: 200,
    onDrop: (evt: MouseEvent): void => {
      evt.stopPropagation();
      evt.preventDefault();
    },
    onDragleave: (evt: MouseEvent): void => {
      leaveCheckTimerItem = window.setTimeout(() => {
        if (
          !dragEnterTargetItem?.contains(
            document.elementFromPoint(evt.clientX, evt.clientY) as Node,
          )
        ) {
          dragEnterTargetItem = null;
          isOverItemKey.value = '';
        }
      }, 50); // 延迟一点判断
    },
  };

  const handleItemAdd = (evt: IData, _node: IRecursiveTreeNode): void => {
    isOverContainer.value = false;
    isOverItemKey.value = '';
    const _draggingNode = getFormNode(evt.from);
    if (_draggingNode) {
      // 判断是否允许拖入
      if (props.allowDrop && !props.allowDrop(_draggingNode, _node, 'inner'))
        return;

      onDrop(_draggingNode, _node, 'inner');
    }
  };

  const handleAdd = (evt: IData): void => {
    isOverContainer.value = false;
    isOverItemKey.value = '';
    const _draggingNode = evt.from && getFormNode(evt.from);
    const _dropNode = props.node;

    if (_draggingNode && _dropNode) {
      // 判断是否允许拖入
      if (
        props.allowDrop &&
        !props.allowDrop(_draggingNode, _dropNode, 'inner')
      )
        return;

      onDrop(_draggingNode, props.node, 'inner');
    }
  };

  return {
    groupOptions,
    draggableOptions,
    isOverContainer,
    isCenter,
    itemGroupOptions,
    draggableItemOptions,
    isOverItemKey,
    handleDragoverItem,
    handleAdd,
    handleItemAdd,
  };
}
